home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / tex / lametex_.z / lametex_ / lametex / src / breakpath.ps < prev    next >
Encoding:
Text File  |  1992-09-02  |  5.9 KB  |  191 lines

  1. %! This is a PostScript library meant to be included in other files %%%
  2. %% Postscript Code by Jon Monsarrat Copyright 1991
  3. %% permission given for anything except selling this or deleting the header.
  4. %%%%%%%%%%%   -    Approx   array %%%%%%%%%%%%%%%%%
  5. % Approx flattens a path into a series of lines.
  6. % This new flattened path is returned as a triple-array path representation.
  7. % The path is broken into sub-paths which have a double-array representation.
  8. % Each sub-path breaks into vertices which have a single-array representation.
  9. % Each vertex is of the form X Y. We're doing a fill here so any
  10. % unclosed subpaths get closed. That's how postscript normally handles fill.
  11. % It would be easier to use [ X Y ] vertices, but that would waste memory!
  12. /Approx
  13.   {
  14.      [ [ { /Y exch def /X exch def ] [ X Y } 
  15.          { } { } { X Y } pathforall ] ]
  16.   } bind def
  17.  
  18. %%%%%%%%%%%%%%%%%%%  array num bool  SortArray  array   %%%%%%%%%%%%%%%
  19. % SortArray bubble sorts "array" of packets in increasing order, packets are
  20. % groups of numbers and a packet is of size "num". Sorting is done based
  21. % on the value of the first item in each packet. When sorting is done,
  22. % SortArray goes through and deletes all equal packets if "bool" is true.
  23. /SortArray
  24. {
  25.    10 dict begin
  26.    /DelEquals exch def /Pack exch def
  27.    /newlist exch def
  28.    0 Pack newlist length 2 Pack mul sub
  29.    {
  30.      /anum exch def
  31.      anum Pack add Pack newlist length 1 Pack mul sub
  32.      {
  33.        /bnum exch def
  34.        newlist anum get newlist bnum get ge
  35.        {
  36.          /flag true def
  37.          newlist anum get newlist bnum get eq Pack 2 eq and
  38.          {
  39.            /flag false def
  40.            newlist anum 1 add get newlist bnum 1 add get add 0 eq
  41.            {
  42.              newlist anum 1 add get 1 eq ontop xor { /flag true def } if
  43.            } if
  44.          } if
  45.          flag
  46.          {
  47.            0 1 Pack 1 sub
  48.            {
  49.              /ind exch def
  50.              /temp newlist anum ind add get def
  51.              newlist anum ind add newlist bnum ind add get put
  52.              newlist bnum ind add temp put
  53.            } for
  54.          } if
  55.        } if
  56.      } for
  57.    } for
  58.  
  59.    DelEquals      % if this boolean is true, delete all equal packs
  60.    {
  61.      [
  62.        0 Pack newlist length 2 Pack mul sub
  63.        {
  64.          /anum exch def
  65.          newlist anum get newlist anum Pack add get ne
  66.          {
  67.            0 1 Pack 1 sub
  68.            {
  69.              anum add newlist exch get
  70.            } for
  71.          } if
  72.        } for
  73.        0 1 Pack 1 sub
  74.        {
  75.          /ind exch def
  76.          newlist newlist length Pack sub ind add get
  77.        } for
  78.      ]
  79.    } 
  80.    {
  81.      newlist
  82.    } ifelse
  83.    end % temp dict 10
  84. } bind def
  85.  
  86. %%%%%%%%%%%%%%%%%%     bool     CheeseY      X1 W1  or nothing  %%%%%%%%%%
  87. % CheeseY uses defined variables Y1 (a number), oldx, oldy, newx, newy.
  88. % CheeseY asks "does the line segment bounded by oldxy, newxy cross y=Y1?
  89. % If so, CheeseY leaves X1 W on the stack, where (X1,Y1) is the point of
  90. % intersection. The winding value W is calculated from the sign of the slope.
  91. % CheeseY takes one argument which is a boolean value. This boolean is
  92. % true is the Y1 value is "on top" of the region of interest, false if "below".
  93. % This is to deal correctly with line segments which end on the y=Y1 line.
  94. % These special line segments are ignored if they don't pass through the
  95. % region of interest. It would be easier to use [ X W ] but memory wasteful.
  96. /CheeseY
  97. {
  98.   /top exch def
  99.   oldy newy 2 copy gt { exch } if
  100.   Y1 ge exch Y1 le and
  101.   {  
  102.      oldy newy ne
  103.      {
  104.         oldx newx sub oldy newy sub div
  105.         oldy Y1 sub mul oldx exch sub 
  106.         oldy newy lt { 1 } { -1 } ifelse
  107.      }
  108.      {
  109.        newx 0
  110.      } ifelse
  111.  
  112.      % If the line segment does NOT go through region of interest
  113.      % but rather just happens to end on line y=Y1, don't use it.
  114.      oldy Y1 eq
  115.      {
  116.        dup top { -1 } { 1 } ifelse ne { pop pop } if
  117.      }
  118.      {
  119.        newy Y1 eq
  120.        {
  121.          dup top { 1 } { -1 } ifelse ne { pop pop } if
  122.        } if
  123.      } ifelse
  124.   } if
  125. } bind def
  126.  
  127. %%%%%%%%%%%%%%%%%%%%%   array num bool  CheeseWhiz   array  %%%%%%%%%%%%%%%%%
  128. % CheeseWhiz traverses the flattened path as computed by Approx to find
  129. % any points of intersection with the line y=Y1, where Y1 is it's num argument.
  130. % It's boolean argument is true if y=Y1 bounds the region of interest "on top".
  131. % For all points of intersection X1 goes on the stack, where [ X1 Y1 ]
  132. % is the point, BUT ONLY IF the winding value or evenodd calculation says
  133. % to. The winding value is complex and calculated from the sign of the slope.
  134. % CheeseWhiz does this by breaking the path into line segments and passing
  135. % it to CheeseY. The final array of X1 values is sorted, keeping duplicates.
  136. /CheeseWhiz
  137. {
  138.   15 dict begin
  139.   /ontop exch def
  140.   /Y1 exch def
  141.   [ exch
  142.      {
  143.         /oldx (Begin) def
  144.         /flag false def
  145.         {
  146.            flag
  147.            {
  148.              /newy exch def
  149.              oldx (Begin) eq
  150.              { /firstx newx def /firsty newy def} { ontop CheeseY } ifelse
  151.              /oldx newx def /oldy newy def
  152.            }
  153.            {
  154.              /newx exch def
  155.            } ifelse
  156.            /flag flag not def
  157.         } forall
  158.         oldx (Begin) ne
  159.         {
  160.           /newx firstx def  % Even if the subpath is not closed, PostScript
  161.           /newy firsty def  % fill methodology says close it. So wrap around.
  162.           ontop CheeseY       
  163.         } if
  164.      } forall
  165.   ]
  166.   % Sort the array of X W values
  167.   2 false SortArray
  168.   % Now go through and take out X's where there is no inside/outside change
  169.   [ exch
  170.     fillout { LM exch } if
  171.     /winding 0 def
  172.     /inside false def   % always start off outside
  173.     /flag false def
  174.     {
  175.       flag
  176.       {
  177.         winding add /winding exch def
  178.         evenodd not
  179.         {
  180.           winding 0 eq inside xor
  181.           { pop } { /inside inside not def } ifelse
  182.         } if
  183.       } if
  184.       /flag flag not def
  185.     } forall
  186.     fillout { RM } if
  187.   ]
  188.   end  % temp dict 15
  189. } def
  190. %% End of PostScript Path-breaking Library
  191.